/*-
 * UDH.java
 *
 * $LastChangedBy: stein $
 * $LastChangedRevision: 98 $
 * $LastChangedDate: 2007-02-20 15:18:26 +0000 (Tue, 20 Feb 2007) $
 * $HeadURL: svn://localhost/SMS/src/com/googlecode/attention/sms/pdu/UDH.java $
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention.sms.pdu;

import java.util.ArrayList;
import java.util.Arrays;

import com.googlecode.attention.util.IntArrayBuilder;


/** * TP-User-Data-Header (TP-UDH). *  * @author Stein Gunnar Bakkeby */
public class UDH {

  private static final long serialVersionUID = -4143500321566146610L;
  
  /* Field values */
  private UDIE[] udies;

  // TODO this probably need a complete rewrite
  //      update 2008.05.03: Maybe fine as is, perhaps we just create extra
  //      usable classes to handle and interpret the data inside the UHD. 
  
  /**
   * Default constructor, creates the an empty user-data-header.
   */
  public UDH() {
    super();
    udies = new UDIE[0];
  }
  
  public UDH(final UDIE[] udies) {
    this.udies = udies;
  }
  
  /**
   * Constructor, creates the user-data-header. Note that the UDHL should
   * not be included in the argument.
   * 
   * @param udh The UDH data
   */
  public UDH(final int[] udh) {
    parseHeader(udh);
  }
  
  /**
   * Ref. 3GPP TS 23.040 version 5.8.1 Release 5 page 65.
   * 
   * @param udh The user-data-header
   */
  private void parseHeader(final int[] udh) {
    final int length = udh.length;
    final ArrayList<UDIE> tempUDIEs = new ArrayList<UDIE>();
    for (int i = 0; i < length; i++) {
      final int IEIa = udh[i++];
      if (i >= length) break;
      final int IEIDLa = udh[i];
      if (i + IEIDLa >= length) break;
      final int[] data = new int[IEIDLa];
      for (int j = 0; j < IEIDLa; j++) {
        data[j] = udh[i + 1 + j];
      }
      i += IEIDLa;
      tempUDIEs.add(new UDIE(IEIa, data));
    }
    udies = tempUDIEs.toArray(new UDIE[tempUDIEs.size()]);
  }
  
  /**
   * This will add another UDIE.
   * 
   * @param udie The UDIE to add
   */
  public void addUDIE(final UDIE udie) {
    final int currentLength = udies.length;
    final UDIE[] newArray = new UDIE[currentLength + 1];
    System.arraycopy(this.udies, 0, newArray, 0, currentLength);
    newArray[currentLength] = udie;
    this.udies = newArray;
  }
  
  /**
   * This will add all UDIE in the given array.
   * 
   * @param udies The UDIEs to add
   */
  public void addUDIE(final UDIE[] udies) {
    final int currentLength = udies.length;
    final UDIE[] newArray = new UDIE[currentLength + udies.length];
    System.arraycopy(this.udies, 0, newArray, 0, currentLength);
    for (int i = 0; i < udies.length; i++) {
      newArray[currentLength + i] = udies[i];
    }
    this.udies = newArray;
  }
  
  /**
   * This will remove the last added UDIE.
   */
  public void removeLastUDIE() {
    final int currentLength = udies.length;
    final UDIE[] newArray = new UDIE[currentLength - 1];
    System.arraycopy(this.udies, 0, newArray, 0, currentLength - 1);
    this.udies = newArray;
  }
  
  /**
   * Returns the int array. 
   * 
   * @return int[]
   */
  public int[] toArray() {
    final int length = udies.length;
    final IntArrayBuilder iab = new IntArrayBuilder();
    for (int i = 0; i < length; i++) {
      iab.append(udies[i].getData());
    }
    return iab.toArray();
  }
  
  public int getLength() {
    final int length = udies.length;
    int output = 0;
    for (int i = 0; i < length; i++) {
      output += udies[i].getLength();
    }
    return output;
  }
  
  /**
   * This will return the information elements of this user-data-header.
   * 
   * @return A list of UDIEs, or null if none present
   */
  public UDIE[] getInformationElements() {
    return udies;
  }
  
  /**
   * This will overwrite the currently set information elements, if any.
   * 
   * @param udies The information elements to set
   * @see #addUDIE(UDIE)
   * @see #addUDIE(UDIE[])
   */
  public void setInformationElements(final UDIE[] udies) {
    this.udies = udies;
  }
  
  public String toString() {
    return Arrays.toString(toArray());
  }
}